<?php
/**
 * Created by PhpStorm.
 * User: lenovo
 * Date: 2020/6/11
 * Time: 20:54
 */

namespace App\Services;


use App\Model\AppModel;
use App\Model\BlacklistModel;
use App\Model\UserModel;
use EasySwoole\Jwt\Jwt;
use EasySwoole\Component\TableManager;
use EasySwoole\EasySwoole\Config;
use EasySwoole\EasySwoole\ServerManager;

class UserService
{

    /**
     * 用户登录
     */
    public function userLogin($param){
        $server = ServerManager::getInstance()->getSwooleServer();
        $nickname = isset($param['extra']['nickname'])?$param['extra']['nickname']:'';
        $head = isset($param['extra']['head'])?$param['extra']['head']:'';
        $type = isset($param['extra']['type'])?$param['extra']['type']:1;
        $data = array(
            'extra'=>isset($param['extra'])?$param['extra']:''
        );
        $messageArr = array(
            'code'=>ReponseCodeService::CODE_BAD_REQUEST,
            'data'=>json_encode($data,JSON_FORCE_OBJECT),
            'action'=>'login',
            'nonce'=>$param['nonce'],
            'time'=>HelpService::msectime(),
        );
        $fdToAppTable = TableManager::getInstance()->get(Config::getInstance()->getConf('CHAT.fd_to_app'));
        $fdToApp =  $fdToAppTable->get($param['fd']);
        $userInfo = $this->loginByAppUserId($param['extra']['access_key'],$param['extra']['app_user_id'],$head,$nickname,$type);

        if(!is_object($userInfo)){
            $messageArr['msg'] = ReponseCodeService::$phrases[ReponseCodeService::CODE_BAD_REQUEST];
            $messageArr['code'] = ReponseCodeService::CODE_BAD_REQUEST;
            return    $server->push($param['fd'], HelpService::aesEncrypt(json_encode($messageArr), $fdToApp['access_key'], $fdToApp['secret_key']));
        }

        $onlineData['nickname'] = $userInfo['nickname'];
        $onlineData['fd'] = $param['fd'];
        $onlineData['server'] = Config::getInstance()->getConf('APP.CURRENT.host');
        $onlineData['head'] = $userInfo['head'];
        $onlineData['user_id'] = $userInfo['id'];
        $onlineData['app_user_id'] = $userInfo['app_user_id'];
        $onlineData['app_id'] = $userInfo['app_id'];
        $onlineData['login_time'] = HelpService::msectime();
        $onlineData['access_key'] = $fdToApp['access_key'];
        $onlineData['secret_key'] = $fdToApp['secret_key'];
        $onlineData['type'] = $userInfo['type'];
        $table = TableManager::getInstance()->get(Config::getInstance()->getConf('CHAT.online_user'));

        //全部在线用户集合
        #这边后面要加判断，是否已经在线，在线发个退出通知
        $table->set($userInfo['id'], $onlineData);
        //绑定用户id
        echo $userInfo['id'].'连接到服务器了'. $param['fd'].PHP_EOL;
      #  echo '登录信息'.PHP_EOL;
        
        #绑定fd-uid
        $server->bind($param['fd'],$userInfo['id']);

        #通知中间服务器
        $masterService = new MasterService();
        $masterService->online($onlineData);

        $userService = new UserService();
        #判断是否登录冲突
        if(isset($param['extra']['token'])){
           echo '客户端有token'.PHP_EOL;
            $token = $param['extra']['token'];
        }else{
            echo '客户端没token'.PHP_EOL;
            $token = $userService->makeToken($userInfo);
        }
        go(function ()use($param,$token,$userInfo,$messageArr,$fdToApp) {
            $server = ServerManager::getInstance()->getSwooleServer();
            $redis = new \EasySwoole\Redis\Redis(new \EasySwoole\Redis\Config\RedisConfig([
                'host'      => Config::getInstance()->getConf('REDIS.host'),
                'port'      => Config::getInstance()->getConf('REDIS.port'),
                'auth' => Config::getInstance()->getConf('REDIS.auth'),
                'serialize' => \EasySwoole\Redis\Config\RedisConfig::SERIALIZE_NONE
            ]));

            if($token!=$redis->hGet(Config::getInstance()->getConf('APP.user_token'),$userInfo['id'])){
                $messageArr['msg'] = ReponseCodeService::$phrases[ReponseCodeService::CODE_UNAUTHORIZED];
                $messageArr['code'] = ReponseCodeService::CODE_UNAUTHORIZED;
                #这边，后续会主动断开socket
                return    $server->push($param['fd'], HelpService::aesEncrypt(json_encode($messageArr), $fdToApp['access_key'], $fdToApp['secret_key']));
            }
            $userInfo['token'] = $token;
            $messageArr['msg'] = ReponseCodeService::$phrases[ReponseCodeService::CODE_OK];
            $messageArr['code'] = ReponseCodeService::CODE_OK;
            $data['extra'] =  $userInfo;
            $messageArr['data'] = json_encode($data);
            return    $server->push($param['fd'], HelpService::aesEncrypt(json_encode($messageArr), $fdToApp['access_key'], $fdToApp['secret_key']));
        });
    }


    /**生成token
     * @param $userInfo
     */
    public function makeToken($userInfo){
       /* $jwtObject = Jwt::getInstance()
            //    ->setSecretKey('easyswoole') // 秘钥
            ->publish();

        $jwtObject->setAlg('HMACSHA256'); // 加密方式
        $jwtObject->setAud('user'); // 用户
        $jwtObject->setExp(time()+86400*30); // 过期时间
        $jwtObject->setIat(time()); // 发布时间
        $jwtObject->setIss('easyswoole'); // 发行人
        $jwtObject->setJti(md5(time())); // jwt id 用于标识该jwt
        $jwtObject->setNbf(time()); // 在此之前不可用
        $jwtObject->setSub('用户信息'); // 主题
        // 自定义数据
        $jwtObject->setData($userInfo);
        $token = $jwtObject->__toString();*/
        $token = $userInfo['id'].time();
        go(function ()use($userInfo,$token) {
            $redis = new \EasySwoole\Redis\Redis(new \EasySwoole\Redis\Config\RedisConfig([
                'host'      => Config::getInstance()->getConf('REDIS.host'),
                'port'      => Config::getInstance()->getConf('REDIS.port'),
                'auth' => Config::getInstance()->getConf('REDIS.auth'),
                'serialize' => \EasySwoole\Redis\Config\RedisConfig::SERIALIZE_NONE
            ]));
            $redis->hSet(Config::getInstance()->getConf('APP.user_token'),$userInfo['id'],$token);
        });

        return  $token;
    }

    /**
     * 获取其他人用户信息
     */
    public function getOtherUserInfo($param,$userInfo){
        try{
        $userInfo = UserModel::create()->field('nickname,head,type')->get(['app_user_id'=>$param['extra']['app_user_id'],'app_id'=>$userInfo['app_id']]);
        if(empty( $userInfo)){
            return ReponseCodeService::CODE_USER_NOT_FUND;
        }
        return $userInfo;
      }catch(\Throwable $t){
        return ReponseCodeService::CODE_FAILE;
        }
    }

    /**
     * 修改用户信息
     */
    public function updateUserInfo($param,$userInfo){
        try{
            $updateInfo = array();
            if(isset($param['extra']['nickname'])&&!empty($param['extra']['nickname'])){
                $updateInfo['nickname'] = $param['extra']['nickname'];
            }
            if(isset($param['extra']['head'])&&!empty($param['extra']['head'])){
                $updateInfo['head'] = $param['extra']['head'];
            }

            if(empty( $updateInfo )){
                return ReponseCodeService::CODE_EMPTY;
            }

            if(UserModel::create()->update($updateInfo,['id'=>$userInfo['id']])){
                #这边做异步任务，批量通知好友、群成员头像变了
                $broadCastService = new BroadcastService();
                $broadCastService->accountChange($userInfo);
                return ReponseCodeService::CODE_OK;
            }
            return ReponseCodeService::CODE_FAILE;
        }catch(\Throwable $t){
            return ReponseCodeService::CODE_SERVICE_UNAVAILABLE;
        }
    }


    /**获取黑名单列表
     * @param $userInfo
     */
   public function getBlacklist($userInfo){
       try{
           $list = BlacklistModel::create()
               ->join('users','users.id=blacklist.dislike_user_id','left')
               ->field('users.id,users.app_user_id,users.nickname,users.head')
              ->all(['blacklist.user_id'=>$userInfo['id']]);
           return  $list;
         }catch(\Throwable $t){
           echo $t->getMessage();
            return ReponseCodeService::CODE_SERVICE_UNAVAILABLE;
       }
   }

    /**添加黑名单
     * @param $param
     * @param $userInfo
     * @return int
     */
    public function addBlacklist($param,$userInfo){
        try{
          $dislikeUser = UserModel::create()->get(['app_user_id'=>$param['extra']['app_user_id'],'app_id'=>$userInfo['app_id']]);
            if(empty($dislikeUser)){
                return ReponseCodeService::CODE_USER_NOT_FUND;
            }
           #校验是否在黑名单
           if(BlacklistModel::create()->get(['user_id'=>$userInfo['id'],'dislike_user_id'=>$dislikeUser['id']])){
                return ReponseCodeService::CODE_BLACK_LIST;
           }
           #创建黑名单
            $blackData['user_id'] = $userInfo['id'];
            $blackData['dislike_user_id'] = $dislikeUser['id'];
            $blackData['created_at'] = date("Y-m-d H:i:s").'.000';
            $blackData['updated_at'] = date("Y-m-d H:i:s").'.000';
            if(BlacklistModel::create()->data($blackData)->save()){
                return ReponseCodeService::CODE_OK;
            }
            return ReponseCodeService::CODE_FAILE;
        }catch(\Throwable $t){
            echo $t->getMessage();
            return ReponseCodeService::CODE_SERVICE_UNAVAILABLE;
        }
    }

    /**
     * 删除黑名单
     */
    public function delBlackList($param,$userInfo){
        try{
            $dislikeUser = UserModel::create()->get(['app_user_id'=>$param['extra']['app_user_id'],'app_id'=>$userInfo['app_id']]);
            if(empty($dislikeUser)){
                return ReponseCodeService::CODE_USER_NOT_FUND;
            }
            #校验是否在黑名单
            if(!BlacklistModel::create()->get(['user_id'=>$userInfo['id'],'dislike_user_id'=>$dislikeUser['id']])){
                return ReponseCodeService::CODE_NOT_BLACK_LIST;
            }

            if(BlacklistModel::create()->destroy(['user_id'=>$userInfo['id'],'dislike_user_id'=>$dislikeUser['id']])){
                return ReponseCodeService::CODE_OK;
            }
            return ReponseCodeService::CODE_FAILE;
        }catch(\Throwable $t){

            return ReponseCodeService::CODE_SERVICE_UNAVAILABLE;
        }
    }
    /**是否注册过
     * @param $accessKey
     * @param $appUserId
     * @param $type
     */
    public function isRegister($accessKey,$appUserId,$type){
        try{
            $app = AppModel::create()->get(['access_key'=>$accessKey])->field('id');
            if(empty(  $app)){
                return ReponseCodeService::CODE_USER_NOT_FUND;
            }
            $userInfo = UserModel::create()->get(['app_user_id'=>$appUserId,'app_id'=>$app['id'],'type'=>$type]);
            if(!empty( $userInfo)){
                return true;
            }
            return false;
         }catch(\Throwable $t){
            return ReponseCodeService::CODE_SERVICE_UNAVAILABLE;
        }
    }

    /**
     * @param $countryCode
     * @param $mobile
     * @return mixed
     */
    function loginByMobile($countryCode,$mobile){
        $userModel = new UserModel();
        $info = $userModel->get(['mobile'=>$mobile,'country_code'=>$countryCode]);

        if(empty($info)){
            $info['nickname'] = $mobile;
            $info['country_code'] = $countryCode;
            $info['mobile'] = $mobile;
            $info['imid']  = HelpService::createImid();
            $regRet =  $userModel->createUser($info);

            if( $regRet['error']!=0){
                return false;
            }
            $info =  $userModel->get(['mobile'=>$mobile,'country_code'=>$countryCode]);
            $is_new = 1;
        }else{
            $is_new = 0;
        }

        $userInfo =   $this->login($info['id']);

        $userInfo['is_new'] = $is_new;
        return $userInfo;
    }

    /**
     * @param $userId
     * @return mixed
     * @throws \EasySwoole\Mysqli\Exception\Exception
     * @throws \EasySwoole\ORM\Exception\Exception
     * @throws \Throwable
     */
  function login($userId){
        $userModel = new UserModel();
        $userInfo = $userModel->get($userId);

       $jwtObject = Jwt::getInstance()
          //    ->setSecretKey('easyswoole') // 秘钥
          ->publish();

      $jwtObject->setAlg('HMACSHA256'); // 加密方式
      $jwtObject->setAud('user'); // 用户
      $jwtObject->setExp(time()+86400*30); // 过期时间
      $jwtObject->setIat(time()); // 发布时间
      $jwtObject->setIss('easyswoole'); // 发行人
      $jwtObject->setJti(md5(time())); // jwt id 用于标识该jwt
      $jwtObject->setNbf(time()); // 在此之前不可用
      $jwtObject->setSub('用户信息'); // 主题
      // 自定义数据
      $jwtObject->setData($userInfo);

      // 最终生成的token
      $token = $jwtObject->__toString();
      $userInfo['token'] = $token;
      #获取ak
      $userInfo['access_key'] = Config::getInstance()->getConf('APP.AES.AES_KEY');
      $userInfo['secret_key'] = Config::getInstance()->getConf('APP.AES.IV');
      return $userInfo;
  }

    /**
     * @param $accessKey
     * @param $head
     * @param $nickname
     * @param $appId
     * @param $type用户类型
     * @return array|bool|mixed
     */
  function loginByAppUserId($accessKey,$appUserId,$head='',$nickname='',$type=UserModel::USER_TYPE_NORMAL){
      try{
          $app = AppModel::create()->get(['access_key'=>$accessKey]);
          if(empty(  $app)){
              return false;
          }
          $userModel = new UserModel();
          $userInfo = $userModel->get(['app_user_id'=>$appUserId,'app_id'=> $app['id'],'type'=>$type]);
          if(empty($userInfo)){
              #不存在的用户，直接返回错误
              $info['nickname'] = $nickname;
              $info['head'] = $head;
              $info['app_id'] = $app['id'];
              $info['app_user_id'] = $appUserId;
              $info['type'] = $type;
              $regRet =  $userModel->createUser($info);
              if( $regRet==false){
                  return false;
              }
              $userInfo = $userModel->get(['app_user_id'=>$appUserId,'app_id'=>$app['id']]);
         }else{//更新同步昵称头像
              //更新
              if($userInfo['nickname']!=$nickname||$userInfo['head']!=$head){
                  $info['nickname'] = $nickname;
                  $info['head'] = $head;
                  $info['updated_at'] = HelpService::msectimeToStr(HelpService::msectime());
                  UserModel::create()->update($info,['app_user_id'=>$appUserId,'app_id'=> $app['id'],'type'=>$type]);
                  $userInfo = $userModel->get(['app_user_id'=>$appUserId,'app_id'=> $app['id'],'type'=>$type]);
                  $broadcastService = new BroadcastService();
                  $broadcastService->accountChange($userInfo);
              }
          }
          return     $userInfo;
      }catch(\Throwable $t){
         return false;
      }
  }

    /**获取用户在线信息
     * @param $userId
     */
  public function getUserOnlineInfo($userId){
      $table = TableManager::getInstance()->get(Config::getInstance()->getConf('CHAT.online_user'));
      $userInfo = $table->get($userId);
      if(!empty($userInfo)){
          return $userInfo;
      }
      //从中间服务器拉取
      return  $this->getUserOnlienInfoFromMaster($userId);
  }

    /**
     * 从中间服务器拉取在线信息
     */
  public function getUserOnlienInfoFromMaster($userId){
      $maserService = new MasterService();
      $userInfo = $maserService->getUserOnlineInfo($userId);
      return $userInfo;
  }

    /**
     * 更新本机用户在线信息
     */
  public function updateLocalUserOnlineInfo($userId){
        $userOnlineInfo = $this->getUserOnlienInfoFromMaster($userId);
        if(empty($userOnlineInfo)){
            //如果本地存在旧的数据，直接干掉
            return true;
        }
        //更新数据
      $table = TableManager::getInstance()->get(Config::getInstance()->getConf('CHAT.online_user'));
      $onlineData['nickname'] = $userOnlineInfo['nickname'];
      $onlineData['fd'] = $userOnlineInfo['fd'];
      $onlineData['server'] = $userOnlineInfo['server'];
      $onlineData['head'] = $userOnlineInfo['head'];
      $table->set($userId, $onlineData);
        return true;
  }


  public function findByAppUserId($appUserId){
      try{
          return  UserModel::create()->get(['app_user_id'=>$appUserId]);
      }catch(\Throwable $t){
          return ReponseCodeService:: CODE_SERVICE_UNAVAILABLE;
      }
  }

}